#pragma once
#include "availabilitycheckhelper.h"

template <typename tCheckAvailability>
class CFourierTransformFactoryBase
{
private:
	static AvailabilityCheckHelper	checker;
public:
	static bool HasBeenCheckedAndIsAvailable()
	{
		if (CFourierTransformFactoryBase<tCheckAvailability>::checker.HasAlreadyBeenChecked())
		{
			return CFourierTransformFactoryBase<tCheckAvailability>::checker.IsAvailable();
		}

		return false;
	}

	static bool GetIsAvailable()
	{
		if (CFourierTransformFactoryBase<tCheckAvailability>::checker.HasAlreadyBeenChecked())
		{
			return  CFourierTransformFactoryBase<tCheckAvailability>::checker.IsAvailable();
		}

		if (!tCheckAvailability::CanLoadLibrary())
		{
			CFourierTransformFactoryBase<tCheckAvailability>::checker.SetAvailability(false);
			return false;
		}

		CFourierTransformFactoryBase<tCheckAvailability>::checker.SetAvailability(tCheckAvailability::CanOperate());
		return CFourierTransformFactoryBase<tCheckAvailability>::checker.IsAvailable();
	}
};

template <typename tCheckAvailability>
AvailabilityCheckHelper CFourierTransformFactoryBase<tCheckAvailability>::checker;


struct NullAvailabilityChecker
{
	static bool CanLoadLibrary(){ return true; }
	static bool CanOperate(){ return true; }
};

typedef CFourierTransformFactoryBase<NullAvailabilityChecker> CFourierTransformFactoryBaseNullCheck;

template <typename tCheckAvailability>
class CFourierTransformFactoryBaseEmptyDefaultImp : public FTLib::IFourierTransformFactory, public CFourierTransformFactoryBase < tCheckAvailability >
{
	virtual std::shared_ptr<FTLib::IRealToComplex_PackedFftwComplex> CreateRealToComplexPackedFftw(const Options& opts)
	{
		return std::shared_ptr < FTLib::IRealToComplex_PackedFftwComplex>();
	}

	virtual std::shared_ptr<FTLib::IRealToComplex_PackedIppComplex> CreateRealToComplexPackedIpp(const Options& opts)
	{
		return std::shared_ptr < FTLib::IRealToComplex_PackedIppComplex>();
	}

	virtual std::shared_ptr<FTLib::IRealToComplex_Complex> CreateRealToComplex(const Options& opts)
	{
		return std::shared_ptr < FTLib::IRealToComplex_Complex>();
	}

	virtual std::shared_ptr<FTLib::IRealToComplex_Complex> CreateRealToComplex_Shifted(const Options& opts)
	{
		return std::shared_ptr < FTLib::IRealToComplex_Complex>();
	}

	virtual std::shared_ptr<FTLib::IComplexToComplexFwd_Complex> CreateComplexToComplexFwd(const Options& opts)
	{
		return std::shared_ptr < FTLib::IComplexToComplexFwd_Complex>();
	}

	virtual std::shared_ptr<FTLib::IComplexToComplexInv_Complex> CreateComplexToComplexInv(const Options& opts)
	{
		return std::shared_ptr < FTLib::IComplexToComplexInv_Complex>();
	}

	/*virtual std::shared_ptr<FTLib::IComplexToReal_PackedIppComplex> CreateComplexToRealPackedIpp(const Options& opts)
	{
		return std::shared_ptr<FTLib::IComplexToReal_PackedIppComplex>();
	}*/
	virtual std::shared_ptr<FTLib::IComplexHermitianToReal> CreateComplexHermitianToReal(const Options& opts)
	{
		return std::shared_ptr<FTLib::IComplexHermitianToReal>();
	}
};